﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Input;

namespace BattleTank3D
{
    class Jogo
    {

        Camera camera;
        Camera mapCamera;
        SpriteBatch spriteBatch;

        Model tank, tank2;

        RasterizerState solid = new RasterizerState();

        RasterizerState wired = new RasterizerState();
        
        /// <summary>
        /// viewport do mapa, deve mostrar a cena toda
        /// </summary>
        Viewport mapViewport;

        /// <summary>
        /// Fonte do texto utilizada nos creditos
        /// </summary>
        SpriteFont fonteExplicacaoJogo;

        SkySphere sky;

        int pontuacao = 0, vidas = 5;

        public Jogo(SpriteBatch sprbatch)
        {
            this.spriteBatch = sprbatch;
        }

        /// <summary>
        /// Carrega as variaveis do jogo
        /// </summary>
        public void Initialize()
        {
            
        }

        /// <summary>
        /// Carrega o conteudo externo do jogo, como musica, imagens, fontes de texto, etc.
        /// </summary>
        /// <param name="GraphicsDevice">Objeto que contem as definições de video do objeto Principal</param>
        /// <param name="Content">Objeto que contem a referencia da localização do conteúdo externo do objeto Principal</param>
        public void LoadContent(GraphicsDevice GraphicsDevice, ContentManager Content, Viewport defaultViewport)
        {
            camera = new Camera(defaultViewport);
            
            tank = Content.Load<Model>("Modelos/Tank_Atari");
            tank2 = Content.Load<Model>("Modelos/Tank_Atari");

            fonteExplicacaoJogo = Content.Load<SpriteFont>("Fonts/explicacaoJogoFont");


            wired.FillMode = FillMode.WireFrame;
            solid.FillMode = FillMode.Solid;

            // Definição do Viewport principal e secundário
            mapViewport = defaultViewport;
            mapViewport.Width = defaultViewport.Width/4;
            mapViewport.Height = defaultViewport.Height/4;
            mapViewport.X = (defaultViewport.Width/2) - mapViewport.Width/2;
            mapViewport.Y = 0;

            mapCamera = new Camera(mapViewport);

            sky = new SkySphere(Content, GraphicsDevice,
                Content.Load<TextureCube>("Imagens/Planos_de_Fundo/black_sky"));    
        }

        /// <summary>
        /// Metodo que irá atualizar o estado dos objetos no jogo
        /// </summary>
        /// <param name="keyboard">Objeto que contem o evento capturado pelo teclado</param>
        /// <param name="old_keyboard">Objeto que contem o ultimo evento capturado pelo teclado</param>
        /// <param name="GraphicsDevice">Objeto que contem as definições de video do objeto Principal</param>
        public void Update(KeyboardState keyboard, KeyboardState old_keyboard, GraphicsDevice GraphicsDevice)
        //public void Update(KeyboardState keyboard, KeyboardState old_keyboard)
        {
           
            if ((keyboard.IsKeyDown(Keys.X)) && !(old_keyboard.IsKeyDown(Keys.X)))
            {
                GraphicsDevice.RasterizerState = solid;
            }

            if ((keyboard.IsKeyDown(Keys.Z)) && !(old_keyboard.IsKeyDown(Keys.Z)))
            {
                GraphicsDevice.RasterizerState = wired;
            }

            camera.Update();
            mapCamera.Update();
        }

        /// <summary>
        /// Metodo que trata a apresentação grafica do jogo
        /// </summary>
        /// <param name="gameTime">Objeto que contem o "tempo do jogo"</param>
        /// <param name="GraphicsDevice">Objeto que contem as definições de video do objeto Principal</param>
        public void Draw(GameTime gameTime, GraphicsDevice GraphicsDevice, Viewport defaultViewport)
        {

            //GraphicsDevice.RasterizerState = wired;

            GraphicsDevice.Viewport = defaultViewport;

            camera.Draw();
            
            //spriteBatch.DrawString(this.fonteExplicacaoJogo, mapCamera.viewport.X.ToString(), new Vector2(0, 50), Color.Yellow);                    
                    
            sky.Draw(camera.getView(), camera.getProj(), camera.getAvatarPosition(), new Vector3(10));

            Vector3 pos = new Vector3(1.5f, 0, -5);
            
            tank2.Draw(Matrix.CreateTranslation(pos), camera.getView(), camera.getProj());
            tank.Draw(camera.getWorld(), camera.getView(), camera.getProj());

            // Exibição do HUD
            String HUD = " Score: " +
                         pontuacao +
                         "\n Vidas: " +
                         vidas;
            spriteBatch.DrawString(fonteExplicacaoJogo, HUD, Vector2.Zero, Color.Green);

            GraphicsDevice.Viewport = mapViewport;
            mapCamera.setCameraState(2);
            mapCamera.Draw();            
            tank.Draw(mapCamera.getWorld(), mapCamera.getView(), mapCamera.getProj());
            tank2.Draw(Matrix.CreateTranslation(pos), mapCamera.getView(), mapCamera.getProj());
            
            //GraphicsDevice.Viewport = defaultViewport;

            /*spriteBatch.DrawString(fonteExplicacaoJogo, camera.cameraState.ToString(), new Vector2(0, 50), Color.Yellow);
            String mensagem = "Pressione W para aproximar ou S para afastar a câmera.\n " +
                               "Pressione Q para descer ou E para subir a câmera.\n " +
                               "Pressione A ou D para mover lateralmente a câmera.\n " +
                               "O movimento do mouse determinará a direção para a câmera deve apontar.\n" +
                               "\n Verificar como manter a imagem como \"Wired\"... \n" +
                               "\n\nAperte ESC para voltar";
            spriteBatch.DrawString(fonteExplicacaoJogo, mensagem, new Vector2((GraphicsDevice.DisplayMode.Width / 2) - (fonteExplicacaoJogo.MeasureString(mensagem).X / 2), 200), Color.White);
            */           
        }
    }
}
